home *** CD-ROM | disk | FTP | other *** search
/ Programming Windows (5th Edition) / Programming Windows, 5th ed. - Companion CD (097-0002183)(1999).iso / Chap13 / PopPad / PopPad.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-09  |  15.4 KB  |  457 lines

  1. /*---------------------------------------
  2.    POPPAD.C -- Popup Editor
  3.                (c) Charles Petzold, 1998
  4.   ---------------------------------------*/
  5.  
  6. #include <windows.h>
  7. #include <commdlg.h>
  8. #include "resource.h"
  9.  
  10. #define EDITID   1
  11. #define UNTITLED TEXT ("(untitled)")
  12.  
  13. LRESULT CALLBACK WndProc      (HWND, UINT, WPARAM, LPARAM) ;
  14. BOOL    CALLBACK AboutDlgProc (HWND, UINT, WPARAM, LPARAM) ;
  15.  
  16.      // Functions in POPFILE.C
  17.  
  18. void PopFileInitialize (HWND) ;
  19. BOOL PopFileOpenDlg    (HWND, PTSTR, PTSTR) ;
  20. BOOL PopFileSaveDlg    (HWND, PTSTR, PTSTR) ;
  21. BOOL PopFileRead       (HWND, PTSTR) ;
  22. BOOL PopFileWrite      (HWND, PTSTR) ;
  23.  
  24.      // Functions in POPFIND.C
  25.  
  26. HWND PopFindFindDlg     (HWND) ;
  27. HWND PopFindReplaceDlg  (HWND) ;
  28. BOOL PopFindFindText    (HWND, int *, LPFINDREPLACE) ;
  29. BOOL PopFindReplaceText (HWND, int *, LPFINDREPLACE) ;
  30. BOOL PopFindNextText    (HWND, int *) ;
  31. BOOL PopFindValidFind   (void) ;
  32.  
  33.      // Functions in POPFONT.C
  34.  
  35. void PopFontInitialize   (HWND) ;
  36. BOOL PopFontChooseFont   (HWND) ;
  37. void PopFontSetFont      (HWND) ;
  38. void PopFontDeinitialize (void) ;
  39.  
  40.      // Functions in POPPRNT.C
  41.  
  42. BOOL PopPrntPrintFile (HINSTANCE, HWND, HWND, PTSTR) ;
  43.  
  44.      // Global variables
  45.  
  46. static HWND  hDlgModeless ;
  47. static TCHAR szAppName[] = TEXT ("PopPad") ;
  48.  
  49. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
  50.                     PSTR szCmdLine, int iCmdShow)
  51. {
  52.      MSG       msg ;
  53.      HWND      hwnd ;
  54.      HACCEL    hAccel ;
  55.      WNDCLASS  wndclass ;
  56.      
  57.      wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
  58.      wndclass.lpfnWndProc   = WndProc ;
  59.      wndclass.cbClsExtra    = 0 ;
  60.      wndclass.cbWndExtra    = 0 ;
  61.      wndclass.hInstance     = hInstance ;
  62.      wndclass.hIcon         = LoadIcon (hInstance, szAppName) ;
  63.      wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
  64.      wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
  65.      wndclass.lpszMenuName  = szAppName ;
  66.      wndclass.lpszClassName = szAppName ;
  67.      
  68.      if (!RegisterClass (&wndclass))
  69.      {
  70.           MessageBox (NULL, TEXT ("This program requires Windows NT!"),
  71.                       szAppName, MB_ICONERROR) ;
  72.           return 0 ;
  73.      }
  74.      
  75.      hwnd = CreateWindow (szAppName, NULL,
  76.                           WS_OVERLAPPEDWINDOW,
  77.                           CW_USEDEFAULT, CW_USEDEFAULT,
  78.                           CW_USEDEFAULT, CW_USEDEFAULT,
  79.                           NULL, NULL, hInstance, szCmdLine) ;
  80.      
  81.      ShowWindow (hwnd, iCmdShow) ;
  82.      UpdateWindow (hwnd) ; 
  83.      
  84.      hAccel = LoadAccelerators (hInstance, szAppName) ;
  85.      
  86.      while (GetMessage (&msg, NULL, 0, 0))
  87.      {
  88.           if (hDlgModeless == NULL || !IsDialogMessage (hDlgModeless, &msg))
  89.           {
  90.                if (!TranslateAccelerator (hwnd, hAccel, &msg))
  91.                {
  92.                     TranslateMessage (&msg) ;
  93.                     DispatchMessage (&msg) ;
  94.                }
  95.           }
  96.      }
  97.      return msg.wParam ;
  98. }
  99.  
  100. void DoCaption (HWND hwnd, TCHAR * szTitleName)
  101. {
  102.      TCHAR szCaption[64 + MAX_PATH] ;
  103.      
  104.      wsprintf (szCaption, TEXT ("%s - %s"), szAppName,
  105.                szTitleName[0] ? szTitleName : UNTITLED) ;
  106.      
  107.      SetWindowText (hwnd, szCaption) ;
  108. }
  109.  
  110. void OkMessage (HWND hwnd, TCHAR * szMessage, TCHAR * szTitleName)
  111. {
  112.      TCHAR szBuffer[64 + MAX_PATH] ;
  113.      
  114.      wsprintf (szBuffer, szMessage, szTitleName[0] ? szTitleName : UNTITLED) ;
  115.      
  116.      MessageBox (hwnd, szBuffer, szAppName, MB_OK | MB_ICONEXCLAMATION) ;
  117. }
  118.  
  119. short AskAboutSave (HWND hwnd, TCHAR * szTitleName)
  120. {
  121.      TCHAR szBuffer[64 + MAX_PATH] ;
  122.      int   iReturn ;
  123.      
  124.      wsprintf (szBuffer, TEXT ("Save current changes in %s?"),
  125.                szTitleName[0] ? szTitleName : UNTITLED) ;
  126.      
  127.      iReturn = MessageBox (hwnd, szBuffer, szAppName,
  128.                            MB_YESNOCANCEL | MB_ICONQUESTION) ;
  129.      
  130.      if (iReturn == IDYES)
  131.           if (!SendMessage (hwnd, WM_COMMAND, IDM_FILE_SAVE, 0))
  132.                iReturn = IDCANCEL ;
  133.           
  134.      return iReturn ;
  135. }
  136.  
  137. LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  138. {
  139.      static BOOL      bNeedSave = FALSE ;
  140.      static HINSTANCE hInst ;
  141.      static HWND      hwndEdit ;
  142.      static int       iOffset ;
  143.      static TCHAR     szFileName[MAX_PATH], szTitleName[MAX_PATH] ;
  144.      static UINT      messageFindReplace ;
  145.      int              iSelBeg, iSelEnd, iEnable ;
  146.      LPFINDREPLACE    pfr ;
  147.      
  148.      switch (message)
  149.      {
  150.      case WM_CREATE:
  151.           hInst = ((LPCREATESTRUCT) lParam) -> hInstance ;
  152.           
  153.                // Create the edit control child window
  154.           
  155.           hwndEdit = CreateWindow (TEXT ("edit"), NULL,
  156.                               WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |
  157.                               WS_BORDER | ES_LEFT | ES_MULTILINE |
  158.                               ES_NOHIDESEL | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
  159.                               0, 0, 0, 0,
  160.                               hwnd, (HMENU) EDITID, hInst, NULL) ;
  161.           
  162.           SendMessage (hwndEdit, EM_LIMITTEXT, 32000, 0L) ;
  163.           
  164.                // Initialize common dialog box stuff
  165.           
  166.           PopFileInitialize (hwnd) ;
  167.           PopFontInitialize (hwndEdit) ;
  168.           
  169.           messageFindReplace = RegisterWindowMessage (FINDMSGSTRING) ;
  170.           
  171.           DoCaption (hwnd, szTitleName) ;
  172.           return 0 ;
  173.           
  174.      case WM_SETFOCUS:
  175.           SetFocus (hwndEdit) ;
  176.           return 0 ;
  177.           
  178.      case WM_SIZE: 
  179.           MoveWindow (hwndEdit, 0, 0, LOWORD (lParam), HIWORD (lParam), TRUE) ;
  180.           return 0 ;
  181.           
  182.      case WM_INITMENUPOPUP:
  183.           switch (lParam)
  184.           {
  185.           case 1:             // Edit menu
  186.                
  187.                     // Enable Undo if edit control can do it
  188.                
  189.                EnableMenuItem ((HMENU) wParam, IDM_EDIT_UNDO,
  190.                     SendMessage (hwndEdit, EM_CANUNDO, 0, 0L) ?
  191.                                              MF_ENABLED : MF_GRAYED) ;
  192.                
  193.                     // Enable Paste if text is in the clipboard
  194.                
  195.                EnableMenuItem ((HMENU) wParam, IDM_EDIT_PASTE,
  196.                     IsClipboardFormatAvailable (CF_TEXT) ?
  197.                                              MF_ENABLED : MF_GRAYED) ;
  198.                
  199.                     // Enable Cut, Copy, and Del if text is selected
  200.                
  201.                SendMessage (hwndEdit, EM_GETSEL, (WPARAM) &iSelBeg,
  202.                                                  (LPARAM) &iSelEnd) ;
  203.                
  204.                iEnable = iSelBeg != iSelEnd ? MF_ENABLED : MF_GRAYED ;
  205.                
  206.                EnableMenuItem ((HMENU) wParam, IDM_EDIT_CUT,   iEnable) ;
  207.                EnableMenuItem ((HMENU) wParam, IDM_EDIT_COPY,  iEnable) ;
  208.                EnableMenuItem ((HMENU) wParam, IDM_EDIT_CLEAR, iEnable) ;
  209.                break ;
  210.                
  211.           case 2:             // Search menu
  212.                
  213.                // Enable Find, Next, and Replace if modeless
  214.                //   dialogs are not already active
  215.                
  216.                iEnable = hDlgModeless == NULL ?
  217.                               MF_ENABLED : MF_GRAYED ;
  218.                
  219.                EnableMenuItem ((HMENU) wParam, IDM_SEARCH_FIND,    iEnable) ;
  220.                EnableMenuItem ((HMENU) wParam, IDM_SEARCH_NEXT,    iEnable) ;
  221.                EnableMenuItem ((HMENU) wParam, IDM_SEARCH_REPLACE, iEnable) ;
  222.                break ;
  223.           }
  224.           return 0 ;
  225.      
  226.      case WM_COMMAND:
  227.                // Messages from edit control
  228.           
  229.           if (lParam && LOWORD (wParam) == EDITID)
  230.           {
  231.                switch (HIWORD (wParam))
  232.                {
  233.                case EN_UPDATE :
  234.                     bNeedSave = TRUE ;
  235.                     return 0 ;
  236.                     
  237.                case EN_ERRSPACE :
  238.                case EN_MAXTEXT :
  239.                     MessageBox (hwnd, TEXT ("Edit control out of space."),
  240.                                 szAppName, MB_OK | MB_ICONSTOP) ;
  241.                     return 0 ;
  242.                }
  243.                break ;
  244.           }
  245.           
  246.           switch (LOWORD (wParam))
  247.           {
  248.                // Messages from File menu
  249.                
  250.           case IDM_FILE_NEW:
  251.                if (bNeedSave && IDCANCEL == AskAboutSave (hwnd, szTitleName))
  252.                     return 0 ;
  253.                
  254.                SetWindowText (hwndEdit, TEXT ("\0")) ;
  255.                szFileName[0]  = '\0' ;
  256.                szTitleName[0] = '\0' ;
  257.                DoCaption (hwnd, szTitleName) ;
  258.                bNeedSave = FALSE ;
  259.                return 0 ;
  260.                
  261.           case IDM_FILE_OPEN:
  262.                if (bNeedSave && IDCANCEL == AskAboutSave (hwnd, szTitleName))
  263.                     return 0 ;
  264.                
  265.                if (PopFileOpenDlg (hwnd, szFileName, szTitleName))
  266.                {
  267.                     if (!PopFileRead (hwndEdit, szFileName))
  268.                     {
  269.                          OkMessage (hwnd, TEXT ("Could not read file %s!"),
  270.                                     szTitleName) ;
  271.                          szFileName[0]  = '\0' ;
  272.                          szTitleName[0] = '\0' ;
  273.                     }
  274.                }
  275.                
  276.                DoCaption (hwnd, szTitleName) ;
  277.                bNeedSave = FALSE ;
  278.                return 0 ;
  279.                
  280.           case IDM_FILE_SAVE:
  281.                if (szFileName[0])
  282.                {
  283.                     if (PopFileWrite (hwndEdit, szFileName))
  284.                     {
  285.                          bNeedSave = FALSE ;
  286.                          return 1 ;
  287.                     }
  288.                     else
  289.                     {
  290.                          OkMessage (hwnd, TEXT ("Could not write file %s"),
  291.                                     szTitleName) ;
  292.                          return 0 ;
  293.                     }
  294.                }
  295.                                    // fall through
  296.           case IDM_FILE_SAVE_AS:
  297.                if (PopFileSaveDlg (hwnd, szFileName, szTitleName))
  298.                {
  299.                     DoCaption (hwnd, szTitleName) ;
  300.                     
  301.                     if (PopFileWrite (hwndEdit, szFileName))
  302.                     {
  303.                          bNeedSave = FALSE ;
  304.                          return 1 ;
  305.                     }
  306.                     else
  307.                     {
  308.                          OkMessage (hwnd, TEXT ("Could not write file %s"),
  309.                                     szTitleName) ;
  310.                          return 0 ;
  311.                     }
  312.                }
  313.                return 0 ;
  314.                
  315.           case IDM_FILE_PRINT:
  316.                if (!PopPrntPrintFile (hInst, hwnd, hwndEdit, szTitleName))
  317.                     OkMessage (hwnd, TEXT ("Could not print file %s"),
  318.                                      szTitleName) ;
  319.                return 0 ;
  320.                
  321.           case IDM_APP_EXIT:
  322.                SendMessage (hwnd, WM_CLOSE, 0, 0) ;
  323.                return 0 ;
  324.                
  325.                     // Messages from Edit menu
  326.                
  327.           case IDM_EDIT_UNDO:
  328.                SendMessage (hwndEdit, WM_UNDO, 0, 0) ;
  329.                return 0 ;
  330.                
  331.           case IDM_EDIT_CUT:
  332.                SendMessage (hwndEdit, WM_CUT, 0, 0) ;
  333.                return 0 ;
  334.                
  335.           case IDM_EDIT_COPY:
  336.                SendMessage (hwndEdit, WM_COPY, 0, 0) ;
  337.                return 0 ;
  338.                
  339.           case IDM_EDIT_PASTE:
  340.                SendMessage (hwndEdit, WM_PASTE, 0, 0) ;
  341.                return 0 ;
  342.                
  343.           case IDM_EDIT_CLEAR:
  344.                SendMessage (hwndEdit, WM_CLEAR, 0, 0) ;
  345.                return 0 ;
  346.                
  347.           case IDM_EDIT_SELECT_ALL:
  348.                SendMessage (hwndEdit, EM_SETSEL, 0, -1) ;
  349.                return 0 ;
  350.                
  351.                     // Messages from Search menu
  352.                
  353.           case IDM_SEARCH_FIND:
  354.                SendMessage (hwndEdit, EM_GETSEL, 0, (LPARAM) &iOffset) ;
  355.                hDlgModeless = PopFindFindDlg (hwnd) ;
  356.                return 0 ;
  357.                
  358.           case IDM_SEARCH_NEXT:
  359.                SendMessage (hwndEdit, EM_GETSEL, 0, (LPARAM) &iOffset) ;
  360.                
  361.                if (PopFindValidFind ())
  362.                     PopFindNextText (hwndEdit, &iOffset) ;
  363.                else
  364.                     hDlgModeless = PopFindFindDlg (hwnd) ;
  365.                
  366.                return 0 ;
  367.                
  368.           case IDM_SEARCH_REPLACE:
  369.                SendMessage (hwndEdit, EM_GETSEL, 0, (LPARAM) &iOffset) ;
  370.                hDlgModeless = PopFindReplaceDlg (hwnd) ;
  371.                return 0 ;
  372.                
  373.           case IDM_FORMAT_FONT:
  374.                if (PopFontChooseFont (hwnd))
  375.                     PopFontSetFont (hwndEdit) ;
  376.                
  377.                return 0 ;
  378.                
  379.                     // Messages from Help menu
  380.                
  381.           case IDM_HELP:
  382.                OkMessage (hwnd, TEXT ("Help not yet implemented!"), 
  383.                                 TEXT ("\0")) ;
  384.                return 0 ;
  385.                
  386.           case IDM_APP_ABOUT:
  387.                DialogBox (hInst, TEXT ("AboutBox"), hwnd, AboutDlgProc) ;
  388.                return 0 ;
  389.           }
  390.           break ;
  391.                
  392.      case WM_CLOSE:
  393.           if (!bNeedSave || IDCANCEL != AskAboutSave (hwnd, szTitleName))
  394.                DestroyWindow (hwnd) ;
  395.           
  396.           return 0 ;
  397.           
  398.      case WM_QUERYENDSESSION :
  399.           if (!bNeedSave || IDCANCEL != AskAboutSave (hwnd, szTitleName))
  400.                return 1 ;
  401.           
  402.           return 0 ;
  403.           
  404.      case WM_DESTROY:
  405.           PopFontDeinitialize () ;
  406.           PostQuitMessage (0) ;
  407.           return 0 ;
  408.           
  409.      default:
  410.                // Process "Find-Replace" messages
  411.           
  412.           if (message == messageFindReplace)
  413.           {
  414.                pfr = (LPFINDREPLACE) lParam ;
  415.                
  416.                if (pfr->Flags & FR_DIALOGTERM)
  417.                     hDlgModeless = NULL ;
  418.                
  419.                if (pfr->Flags & FR_FINDNEXT)
  420.                     if (!PopFindFindText (hwndEdit, &iOffset, pfr))
  421.                          OkMessage (hwnd, TEXT ("Text not found!"), 
  422.                                           TEXT ("\0")) ;
  423.                     
  424.                if (pfr->Flags & FR_REPLACE || pfr->Flags & FR_REPLACEALL)
  425.                     if (!PopFindReplaceText (hwndEdit, &iOffset, pfr))
  426.                          OkMessage (hwnd, TEXT ("Text not found!"), 
  427.                                           TEXT ("\0")) ;
  428.                          
  429.                if (pfr->Flags & FR_REPLACEALL)
  430.                     while (PopFindReplaceText (hwndEdit, &iOffset, pfr)) ;
  431.                               
  432.                return 0 ;
  433.           }
  434.           break ;
  435.      }
  436.      return DefWindowProc (hwnd, message, wParam, lParam) ;
  437. }
  438.  
  439. BOOL CALLBACK AboutDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  440. {
  441.      switch (message)
  442.      {
  443.      case WM_INITDIALOG:
  444.           return TRUE ;
  445.           
  446.      case WM_COMMAND:
  447.           switch (LOWORD (wParam))
  448.           {
  449.           case IDOK:
  450.                EndDialog (hDlg, 0) ;
  451.                return TRUE ;
  452.           }
  453.           break ;
  454.      }
  455.      return FALSE ;
  456. }
  457.